/*
* Cbuf.java
* Copyright (C) 2003
* 
* $Id: Cbuf.java,v 1.8 2005/12/18 22:10:09 cawe Exp $
*/
/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
using System;
using Defines = Suake2.UI.Defines;
using Globals = Suake2.UI.Globals;
using Cmd = Suake2.UI.game.Cmd;
using Lib = Suake2.UI.util.Lib;
namespace Suake2.UI.qcommon
{
	
	/// <summary> Cbuf</summary>
	public sealed class Cbuf
	{
		
		//UPGRADE_NOTE: Final was removed from the declaration of 'line '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
		private static readonly sbyte[] line = new sbyte[1024];
		//UPGRADE_NOTE: Final was removed from the declaration of 'tmp '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
		private static readonly sbyte[] tmp = new sbyte[8192];
		
		/// <summary>  </summary>
		public static void  Init()
		{
			SZ.Init(Globals.cmd_text, Globals.cmd_text_buf, Globals.cmd_text_buf.Length);
		}
		
		public static void  InsertText(System.String text)
		{
			
			int templen = 0;
			
			// copy off any commands still remaining in the exec buffer
			templen = Globals.cmd_text.cursize;
			if (templen != 0)
			{
				Array.Copy(Globals.cmd_text.data, 0, tmp, 0, templen);
				SZ.Clear(Globals.cmd_text);
			}
			
			// add the entire text of the file
			Cbuf.AddText(text);
			
			// add the copied off data
			if (templen != 0)
			{
				SZ.Write(Globals.cmd_text, tmp, templen);
			}
		}
		
		/// <param name="clear">
		/// </param>
		internal static void  AddEarlyCommands(bool clear)
		{
			
			for (int i = 0; i < Com.Argc(); i++)
			{
				System.String s = Com.Argv(i);
				if (!s.Equals("+set"))
					continue;
				Cbuf.AddText("set " + Com.Argv(i + 1) + " " + Com.Argv(i + 2) + "\n");
				if (clear)
				{
					Com.ClearArgv(i);
					Com.ClearArgv(i + 1);
					Com.ClearArgv(i + 2);
				}
				i += 2;
			}
		}
		
		/// <returns>
		/// </returns>
		internal static bool AddLateCommands()
		{
			int i;
			int j;
			bool ret = false;
			
			// build the combined string to parse from
			int s = 0;
			int argc = Com.Argc();
			for (i = 1; i < argc; i++)
			{
				s += Com.Argv(i).Length;
			}
			if (s == 0)
				return false;
			
			System.String text = "";
			for (i = 1; i < argc; i++)
			{
				text += Com.Argv(i);
				if (i != argc - 1)
					text += " ";
			}
			
			// pull out the commands
			System.String build = "";
			for (i = 0; i < text.Length; i++)
			{
				if (text[i] == '+')
				{
					i++;
					
					for (j = i; j < text.Length && (text[j] != '+') && (text[j] != '-'); j++)
						;
					
					build += text.Substring(i, (j) - (i));
					build += "\n";
					
					i = j - 1;
				}
			}
			
			ret = (build.Length != 0);
			if (ret)
				Cbuf.AddText(build);
			
			text = null;
			build = null;
			
			return ret;
		}
		
		/// <param name="text">
		/// </param>
		public static void  AddText(System.String text)
		{
			int l = text.Length;
			
			if (Globals.cmd_text.cursize + l >= Globals.cmd_text.maxsize)
			{
				Com.Printf("Cbuf_AddText: overflow\n");
				return ;
			}
			SZ.Write(Globals.cmd_text, Lib.stringToBytes(text), l);
		}
		
		/// <summary>  </summary>
		public static void  Execute()
		{
			
			sbyte[] text = null;
			
			Globals.alias_count = 0; // don't allow infinite alias loops
			
			while (Globals.cmd_text.cursize != 0)
			{
				// find a \n or ; line break
				text = Globals.cmd_text.data;
				
				int quotes = 0;
				int i;
				
				for (i = 0; i < Globals.cmd_text.cursize; i++)
				{
					if (text[i] == '"')
						quotes++;
					if (!(quotes % 2 != 0) && text[i] == ';')
						break; // don't break if inside a quoted string
					if (text[i] == '\n')
						break;
				}
				
				Array.Copy(text, 0, line, 0, i);
				line[i] = 0;
				
				// delete the text from the command buffer and move remaining
				// commands down
				// this is necessary because commands (exec, alias) can insert data
				// at the
				// beginning of the text buffer
				
				if (i == Globals.cmd_text.cursize)
					Globals.cmd_text.cursize = 0;
				else
				{
					i++;
					Globals.cmd_text.cursize -= i;
					//byte[] tmp = new byte[Globals.cmd_text.cursize];
					
					Array.Copy(text, i, tmp, 0, Globals.cmd_text.cursize);
					Array.Copy(tmp, 0, text, 0, Globals.cmd_text.cursize);
					text[Globals.cmd_text.cursize] = (sbyte) '\x0000';
				}
				
				// execute the command line
				int len = Lib.strlen(line);
				
				System.String cmd = new System.String(SupportClass.ToCharArray(line), 0, len);
				Cmd.ExecuteString(cmd);
				
				if (Globals.cmd_wait)
				{
					// skip out while text still remains in buffer, leaving it
					// for next frame
					Globals.cmd_wait = false;
					break;
				}
			}
		}
		
		public static void  ExecuteText(int exec_when, System.String text)
		{
			switch (exec_when)
			{
				
				case Defines.EXEC_NOW: 
					Cmd.ExecuteString(text);
					break;
				
				case Defines.EXEC_INSERT: 
					Cbuf.InsertText(text);
					break;
				
				case Defines.EXEC_APPEND: 
					Cbuf.AddText(text);
					break;
				
				default: 
					Com.Error(Defines.ERR_FATAL, "Cbuf_ExecuteText: bad exec_when");
					break;
				
			}
		}
		
		/*
		* ============ Cbuf_CopyToDefer ============
		*/
		public static void  CopyToDefer()
		{
			Array.Copy(Globals.cmd_text_buf, 0, Globals.defer_text_buf, 0, Globals.cmd_text.cursize);
			Globals.defer_text_buf[Globals.cmd_text.cursize] = 0;
			Globals.cmd_text.cursize = 0;
		}
		
		/*
		* ============ Cbuf_InsertFromDefer ============
		*/
		public static void  InsertFromDefer()
		{
			InsertText(new System.String(SupportClass.ToCharArray(SupportClass.ToByteArray(Globals.defer_text_buf))).Trim());
			Globals.defer_text_buf[0] = 0;
		}
	}
}